package com.dsideal.cloud.cas.client.config;

import com.dsideal.cloud.cas.client.cas.properties.CasConfiguration;
import com.dsideal.cloud.cas.client.cas.service.CasAuthenticationUserDetailsService;
import com.dsideal.cloud.cas.client.filter.CasLogoutFilter;
import com.dsideal.cloud.cas.client.filter.UserTokenFilter;
import com.dsideal.cloud.cas.client.properties.SecurityConfiguration;
import com.dsideal.cloud.common.filter.CorsFilter;
import org.jasig.cas.client.session.SingleSignOutFilter;
import org.jasig.cas.client.validation.Cas20ServiceTicketValidator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.annotation.Order;
import org.springframework.security.cas.ServiceProperties;
import org.springframework.security.cas.authentication.CasAuthenticationProvider;
import org.springframework.security.cas.web.CasAuthenticationEntryPoint;
import org.springframework.security.cas.web.CasAuthenticationFilter;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;

/**
 * Spring Security CAS 核心配置类
 *
 * @author suny
 */
@Configuration
@Order(SecurityProperties.BASIC_AUTH_ORDER)
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class CasSecurityConfig extends WebSecurityConfigurerAdapter {
    //参数
    @Autowired
    private SecurityConfiguration securityConfiguration;
    //cas服务配置
    @Autowired
    private CasConfiguration casConfiguration;

    @Autowired
    @Lazy
    private CasAuthenticationUserDetailsService casAuthenticationUserDetailsService;


    /**
     * 安全策略配置
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers(securityConfiguration.permitPath()).permitAll()
                .anyRequest().authenticated()
                .and()
                .logout()
                .permitAll()
                .and()
                .formLogin().loginPage("/login")/*.permitAll()*/
//                .successHandler(successHandle).permitAll()
//                .failureHandler(failHandler)
                .and()
                .exceptionHandling().authenticationEntryPoint(casAuthenticationEntryPoint())
                .and()
               .addFilter(casAuthenticationFilter())
                //单点登出
                .addFilterBefore(casLogoutFilter(), LogoutFilter.class)
                //登录
                .addFilterBefore(singleSignOutFilter(), CasAuthenticationFilter.class)
                .csrf().disable().cors().and();

        //个人过滤器
//        http.addFilterBefore(userTokenFilter(), UsernamePasswordAuthenticationFilter.class);
    }

    /**
     * 定义认证用户信息获取来源，密码校验规则等
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        super.configure(auth);
        auth.authenticationProvider(casAuthenticationProvider());
    }


/**
     * 自定义的user token校验过滤器
     * @return NginxHeaderFilter
     * @throws Exception
     */
//    @Bean
    public UserTokenFilter userTokenFilter() throws Exception {
        UserTokenFilter userTokenFilter = new UserTokenFilter();
        userTokenFilter.setAuthenticationManager(authenticationManager());
        return userTokenFilter;
    }




/**
     * CAS认证入口
     * @return CasAuthenticationEntryPoint
     */

    @Bean
    public CasAuthenticationEntryPoint casAuthenticationEntryPoint() {
        CasAuthenticationEntryPoint casAuthenticationEntryPoint = new CasAuthenticationEntryPoint();
        casAuthenticationEntryPoint.setLoginUrl(casConfiguration.getCasServerLoginUrl());
        casAuthenticationEntryPoint.setServiceProperties(serviceProperties());
        return casAuthenticationEntryPoint;
    }


/**
     * CAS认证入口的service属性
     * @return ServiceProperties
     */

    @Bean
    public ServiceProperties serviceProperties() {
        ServiceProperties serviceProperties = new ServiceProperties();
        serviceProperties.setService(casConfiguration.getAppServerUrl() + casConfiguration.getAppLoginUrl());
        serviceProperties.setAuthenticateAllArtifacts(true);
        return serviceProperties;
    }


/**
     * CAS认证过滤器
     * @return CasAuthenticationFilter
     * @throws Exception
     */

    @Bean
    public CasAuthenticationFilter casAuthenticationFilter() throws Exception {
        CasAuthenticationFilter casAuthenticationFilter = new CasAuthenticationFilter();
        casAuthenticationFilter.setAuthenticationManager(authenticationManager());
        casAuthenticationFilter.setFilterProcessesUrl(casConfiguration.getAppLoginUrl());
        return casAuthenticationFilter;
    }



/**
     * CAS认证Provider
     * @return CasAuthenticationProvider
     */

    @Bean
    public CasAuthenticationProvider casAuthenticationProvider() {
        CasAuthenticationProvider casAuthenticationProvider = new CasAuthenticationProvider();
        casAuthenticationProvider.setAuthenticationUserDetailsService(casAuthenticationUserDetailsService);
        casAuthenticationProvider.setServiceProperties(serviceProperties());
        casAuthenticationProvider.setTicketValidator(cas20ServiceTicketValidator());
        casAuthenticationProvider.setKey("casAuthenticationProviderKey");
        return casAuthenticationProvider;
    }

    @Bean
    public Cas20ServiceTicketValidator cas20ServiceTicketValidator() {
        return new Cas20ServiceTicketValidator(casConfiguration.getCasServerUrl());
    }


/**
     * CAS单点登录过滤器
     * @return SingleSignOutFilter
     */

    @Bean
    public SingleSignOutFilter singleSignOutFilter() {
        SingleSignOutFilter singleSignOutFilter = new SingleSignOutFilter();
        singleSignOutFilter.setCasServerUrlPrefix(casConfiguration.getCasServerUrl());
        singleSignOutFilter.setIgnoreInitConfiguration(true);
        return singleSignOutFilter;
    }


/**
     * CAS单点登出过滤器
     * @return LogoutFilter
     */

    @Bean
    public CasLogoutFilter casLogoutFilter() {
        CasLogoutFilter logoutFilter = new CasLogoutFilter(casConfiguration.getCasServerLogoutUrl(),
                new SecurityContextLogoutHandler());
        logoutFilter.setFilterProcessesUrl(casConfiguration.getAppLogoutUrl());
        return logoutFilter;
    }


}
